home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Magazine / Morphos / GCC / ppc-amigaos / include / va-ppc.h < prev    next >
C/C++ Source or Header  |  1999-08-25  |  8KB  |  256 lines

  1. /* GNU C varargs support for the PowerPC with either the V.4 or Windows NT calling sequences */
  2.  
  3. #ifndef _WIN32
  4. /* System V.4 support */
  5. /* Define __gnuc_va_list.  */
  6.  
  7. #ifndef __GNUC_VA_LIST
  8. #define __GNUC_VA_LIST
  9.  
  10. #ifndef _SYS_VA_LIST_H
  11. #define _SYS_VA_LIST_H        /* Solaris sys/va_list.h */
  12.  
  13. /* Solaris decided to rename overflow_arg_area to input_arg_area,
  14.    so handle it via a macro.  */
  15. #define __va_overflow(AP) (AP)->overflow_arg_area
  16.  
  17. /* Note that the names in this structure are in the user's namespace, but
  18.    that the V.4 abi explicitly states that these names should be used.  */
  19. typedef struct __va_list_tag {
  20.   unsigned char gpr;        /* index into the array of 8 GPRs stored in the
  21.                    register save area gpr=0 corresponds to r3,
  22.                    gpr=1 to r4, etc. */
  23.   unsigned char fpr;        /* index into the array of 8 FPRs stored in the
  24.                    register save area fpr=0 corresponds to f1,
  25.                    fpr=1 to f2, etc. */
  26.   char *overflow_arg_area;    /* location on stack that holds the next
  27.                    overflow argument */
  28.   char *reg_save_area;        /* where r3:r10 and f1:f8, if saved are stored */
  29. } __va_list[1], __gnuc_va_list[1];
  30.  
  31. #else /* _SYS_VA_LIST */
  32.  
  33. typedef __va_list __gnuc_va_list;
  34. #define __va_overflow(AP) (AP)->input_arg_area
  35.  
  36. #endif /* not _SYS_VA_LIST */
  37. #endif /* not __GNUC_VA_LIST */
  38.  
  39. /* If this is for internal libc use, don't define anything but
  40.    __gnuc_va_list.  */
  41. #if defined (_STDARG_H) || defined (_VARARGS_H)
  42.  
  43. /* Register save area located below the frame pointer */
  44. #ifndef __VA_PPC_H__
  45. #define __VA_PPC_H__
  46. typedef struct {
  47.   long   __gp_save[8];        /* save area for GP registers */
  48.   double __fp_save[8];        /* save area for FP registers */
  49. } __va_regsave_t;
  50.  
  51. /* Macros to access the register save area */
  52. /* We cast to void * and then to TYPE * because this avoids
  53.    a warning about increasing the alignment requirement.  */
  54. #define __VA_FP_REGSAVE(AP,OFS,TYPE)                    \
  55.   ((TYPE *) (void *) (&(((__va_regsave_t *)                \
  56.              (AP)->reg_save_area)->__fp_save[OFS])))
  57.  
  58. #define __VA_GP_REGSAVE(AP,OFS,TYPE)                    \
  59.   ((TYPE *) (void *) (&(((__va_regsave_t *)                \
  60.              (AP)->reg_save_area)->__gp_save[OFS])))
  61.  
  62. /* Common code for va_start for both varargs and stdarg.  We allow all
  63.    the work to be done by __builtin_saveregs.  It returns a pointer to
  64.    a va_list that was constructed on the stack; we must simply copy it
  65.    to the user's variable.  */
  66.  
  67. #define __va_start_common(AP, FAKE) \
  68.   __builtin_memcpy ((AP), __builtin_saveregs (), sizeof(__gnuc_va_list))
  69.  
  70. #ifdef _STDARG_H /* stdarg.h support */
  71.  
  72. /* Calling __builtin_next_arg gives the proper error message if LASTARG is
  73.    not indeed the last argument.  */
  74. #define va_start(AP,LASTARG) \
  75.   (__builtin_next_arg (LASTARG), __va_start_common (AP, 0))
  76.  
  77. #else /* varargs.h support */
  78.  
  79. #define va_start(AP) __va_start_common (AP, 1)
  80. #define va_alist __va_1st_arg
  81. #define va_dcl register int va_alist; ...
  82.  
  83. #endif /* _STDARG_H */
  84.  
  85. #ifdef _SOFT_FLOAT
  86. #define __va_float_p(TYPE)    0
  87. #else
  88. #define __va_float_p(TYPE)    (__builtin_classify_type(*(TYPE *)0) == 8)
  89. #endif
  90.  
  91. #define __va_aggregate_p(TYPE)    (__builtin_classify_type(*(TYPE *)0) >= 12)
  92. #define __va_size(TYPE)        ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long))
  93.  
  94. /* This symbol isn't defined.  It is used to flag type promotion violations
  95.    at link time.  We can only do this when optimizing.  Use __builtin_trap
  96.    instead of abort so that we don't require a prototype for abort.
  97.  
  98.    __builtin_trap stuff is not available on the gcc-2.95 branch, so we just
  99.    avoid calling it for now.  */
  100.  
  101. #ifdef __OPTIMIZE__
  102. extern void __va_arg_type_violation(void) __attribute__((__noreturn__));
  103. #else
  104. #define __va_arg_type_violation()
  105. #endif
  106.  
  107. #define va_arg(AP,TYPE)                               \
  108. __extension__ (*({                               \
  109.   register TYPE *__ptr;                               \
  110.                                        \
  111.   if (__va_float_p (TYPE) && sizeof (TYPE) < 16)               \
  112.     {                                       \
  113.       unsigned char __fpr = (AP)->fpr;                       \
  114.       if (__fpr < 8)                               \
  115.     {                                   \
  116.       __ptr = __VA_FP_REGSAVE (AP, __fpr, TYPE);               \
  117.       (AP)->fpr = __fpr + 1;                       \
  118.     }                                   \
  119.       else if (sizeof (TYPE) == 8)                       \
  120.     {                                   \
  121.       unsigned long __addr = (unsigned long) (__va_overflow (AP));       \
  122.       __ptr = (TYPE *)((__addr + 7) & -8);                   \
  123.       __va_overflow (AP) = (char *)(__ptr + 1);               \
  124.     }                                   \
  125.       else                                   \
  126.     {                                   \
  127.       /* float is promoted to double.  */                   \
  128.       __va_arg_type_violation ();                       \
  129.     }                                   \
  130.     }                                       \
  131.                                        \
  132.   /* Aggregates and long doubles are passed by reference.  */           \
  133.   else if (__va_aggregate_p (TYPE) || __va_float_p (TYPE))           \
  134.     {                                       \
  135.       unsigned char __gpr = (AP)->gpr;                       \
  136.       if (__gpr < 8)                               \
  137.     {                                   \
  138.       __ptr = * __VA_GP_REGSAVE (AP, __gpr, TYPE *);           \
  139.       (AP)->gpr = __gpr + 1;                       \
  140.     }                                   \
  141.       else                                   \
  142.     {                                   \
  143.       TYPE **__pptr = (TYPE **) (__va_overflow (AP));           \
  144.       __ptr = * __pptr;                           \
  145.       __va_overflow (AP) = (char *) (__pptr + 1);               \
  146.     }                                   \
  147.     }                                       \
  148.                                        \
  149.   /* Only integrals remaining.  */                       \
  150.   else                                       \
  151.     {                                       \
  152.       /* longlong is aligned.  */                       \
  153.       if (sizeof (TYPE) == 8)                           \
  154.     {                                   \
  155.       unsigned char __gpr = (AP)->gpr;                   \
  156.       if (__gpr < 7)                           \
  157.         {                                   \
  158.           __gpr += __gpr & 1;                       \
  159.           __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE);           \
  160.           (AP)->gpr = __gpr + 2;                       \
  161.         }                                   \
  162.       else                                   \
  163.         {                                   \
  164.           unsigned long __addr = (unsigned long) (__va_overflow (AP)); \
  165.           __ptr = (TYPE *)((__addr + 7) & -8);               \
  166.           (AP)->gpr = 8;                           \
  167.           __va_overflow (AP) = (char *)(__ptr + 1);               \
  168.         }                                   \
  169.     }                                   \
  170.       else if (sizeof (TYPE) == 4)                       \
  171.     {                                   \
  172.       unsigned char __gpr = (AP)->gpr;                   \
  173.       if (__gpr < 8)                           \
  174.         {                                   \
  175.           __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE);           \
  176.           (AP)->gpr = __gpr + 1;                       \
  177.         }                                   \
  178.       else                                   \
  179.         {                                   \
  180.           __ptr = (TYPE *) __va_overflow (AP);               \
  181.           __va_overflow (AP) = (char *)(__ptr + 1);               \
  182.         }                                   \
  183.     }                                   \
  184.       else                                   \
  185.     {                                   \
  186.       /* Everything else was promoted to int.  */               \
  187.       __va_arg_type_violation ();                       \
  188.     }                                   \
  189.     }                                       \
  190.   __ptr;                                   \
  191. }))
  192.  
  193. #define va_end(AP)    ((void)0)
  194.  
  195. /* Copy __gnuc_va_list into another variable of this type.  */
  196. #define __va_copy(dest, src) *(dest) = *(src)
  197.  
  198. #endif /* __VA_PPC_H__ */
  199. #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
  200.  
  201.  
  202. #else
  203. /* Windows NT */
  204. /* Define __gnuc_va_list.  */
  205.  
  206. #ifndef __GNUC_VA_LIST
  207. #define __GNUC_VA_LIST
  208. typedef char *__gnuc_va_list;
  209. #endif /* not __GNUC_VA_LIST */
  210.  
  211. /* If this is for internal libc use, don't define anything but
  212.    __gnuc_va_list.  */
  213. #if defined (_STDARG_H) || defined (_VARARGS_H)
  214.  
  215. #define __va_start_common(AP, LASTARG, FAKE)                \
  216.   ((__builtin_saveregs ()), ((AP) = ((char *) &LASTARG) + __va_rounded_size (AP)), 0)
  217.  
  218. #ifdef _STDARG_H /* stdarg.h support */
  219.  
  220. /* Calling __builtin_next_arg gives the proper error message if LASTARG is
  221.    not indeed the last argument.  */
  222. #define va_start(AP,LASTARG)                        \
  223.   (__builtin_saveregs (),                        \
  224.    (AP) = __builtin_next_arg (LASTARG),                    \
  225.    0)
  226.  
  227. #else /* varargs.h support */
  228.  
  229. #define va_start(AP)                            \
  230.   (__builtin_saveregs (),                        \
  231.    (AP) = __builtin_next_arg (__va_1st_arg) - sizeof (int),        \
  232.    0)
  233.  
  234. #define va_alist __va_1st_arg
  235. #define va_dcl register int __va_1st_arg; ...
  236.  
  237. #endif /* _STDARG_H */
  238.  
  239. #define __va_rounded_size(TYPE) ((sizeof (TYPE) + 3) & ~3)
  240. #define __va_align(AP, TYPE)                        \
  241.      ((((unsigned long)(AP)) + ((sizeof (TYPE) >= 8) ? 7 : 3))        \
  242.       & ~((sizeof (TYPE) >= 8) ? 7 : 3))
  243.  
  244. #define va_arg(AP,TYPE)                            \
  245. ( *(TYPE *)((AP = (char *) (__va_align(AP, TYPE)            \
  246.                 + __va_rounded_size(TYPE)))            \
  247.         - __va_rounded_size(TYPE)))
  248.  
  249. #define va_end(AP)    ((void)0)
  250.  
  251. /* Copy __gnuc_va_list into another variable of this type.  */
  252. #define __va_copy(dest, src) (dest) = (src)
  253.  
  254. #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
  255. #endif /* Windows NT */
  256.